﻿/**
 * VERSION: 1.01
 * DATE: 7/15/2009
 * AS3 (AS2 is also available)
 * UPDATES AND DOCUMENTATION AT: http://blog.greensock.com/customease/
 **/
package com.greensock.easing
{

	/**
	 * 	Facilitates creating custom bezier eases with the GreenSock Custom Ease Builder tool. It's essentially
	 *  a place to store the bezier segment information for each ease instead of recreating it inside each
	 *  function call which would slow things down. Please use the interactive tool available at
	 *  <a href="http://blog.greensock.com/customease/">http://blog.greensock.com/customease/</a>
	 * to generate the necessary code.<br /><br />
	 *
	 * <b>Copyright 2011, GreenSock. All rights reserved.</b> This work is subject to the terms in <a href="http://www.greensock.com/terms_of_use.html">http://www.greensock.com/terms_of_use.html</a> or for corporate Club GreenSock members, the software agreement that was issued with the corporate membership.
	 *
	 * @author Jack Doyle, jack@greensock.com
	 */
	public class CustomEase
	{
		public static const VERSION:Number=1.01;
		private static var _all:Object={}; //keeps track of all CustomEase instances.
		private var _segments:Array;
		private var _name:String;

		public static function create(name:String, segments:Array):Function
		{
			var b:CustomEase=new CustomEase(name, segments);
			return b.ease;
		}

		public static function byName(name:String):Function
		{
			return _all[name].ease;
		}

		public function CustomEase(name:String, segments:Array)
		{
			_name=name;
			_segments=[];
			var l:int=segments.length;
			for (var i:int=0; i < l; i++)
			{
				_segments[_segments.length]=new Segment(segments[i].s, segments[i].cp, segments[i].e);
			}
			_all[name]=this;
		}

		public function ease(time:Number, start:Number, change:Number, duration:Number):Number
		{
			var factor:Number=time / duration, qty:uint=_segments.length, t:Number, s:Segment;
			var i:int=int(qty * factor);
			t=(factor - (i * (1 / qty))) * qty;
			s=_segments[i];
			return start + change * (s.s + t * (2 * (1 - t) * (s.cp - s.s) + t * (s.e - s.s)));
		}

		public function destroy():void
		{
			_segments=null;
			delete _all[_name];
		}

	}
}

//allows for strict data typing, making lookups faster
internal class Segment
{
	public var s:Number;
	public var cp:Number;
	public var e:Number;

	public function Segment(s:Number, cp:Number, e:Number)
	{
		this.s=s;
		this.cp=cp;
		this.e=e;
	}
}


